<?php
declare(strict_types=1);

/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Jobs;

use App\Model\Time\CpPackages;
use App\Model\Time\ScreenShow;
use Carbon\Carbon;
use Carbon\Traits\Serialization;
use Hyperf\AsyncQueue\Job;
use Hyperf\AsyncQueue\Process\ConsumerProcess;
use Hyperf\DbConnection\Db;
use Hyperf\Process\Annotation\Process;
use App\Service\SocketClientService;
use App\Service\Message\SendPlayerScreenMsgService;
use Hyperf\Utils\ApplicationContext;
use Hyperf\WebSocketServer\Sender;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use function Swoole\Coroutine\Http\post;

class ScreenJob extends Job
{


//    /**
//     * @Inject
//     * @var Sender
//     */
//    protected $sender;

//    use SerializationModel;
//    use Serialization;
    public $playerId;
    public $cpPackageId;
    public $time;
    public $params;




    public $init = false;

    /**^M
     * ............................................................... $maxAttempts+1 ...^M
     *^M
     * @var int^M
     */
    protected $maxAttempts = 0;


    public function __construct($params)
    {
        $playerId = data_get($params, 'player_id', '');
        $cpPackageId = data_get($params, 'cp_package_id', '');
        $time = data_get($params, 'time', '');
        $paramsF = data_get($params, 'params', '');
        $this->playerId = $playerId;
        $this->cpPackageId = $cpPackageId;
        $this->time = $time;
        $this->params = $paramsF;
    }

    public function handle(): void
    {

        // 找出配速异常和缺卡的选手
        // 配速异常简单，但是要计算本次打卡的配速
        // 缺卡看最后一次打卡的点，之前缺卡都缺卡
        $cpPackagePeisu = data_get($this->params, 'cp_peisu', 0);
        $cpPackageWeigth = data_get($this->params, 'cp_weight', 0);
        $cpMileage = data_get($this->params, 'cp_mileage', 0);
        $isNeedNotify = data_get($this->params, 'is_need_nofity', 1);
        $cpId = data_get($this->params, 'cp_id', 1);
        info('job');
        $player = Db::table('players')->where('id', '=', $this->playerId)->first();
        $playerId = data_get($player, 'id', '');
        $packageId = data_get($player, 'package_id', '');
        $signId = data_get($player, 'sign_id', '');
        $package = Db::table('game_packages')->where('id', '=', $packageId)->select('qiang_at', 'pak_type')->first();
        $qiangAt = data_get($package, 'qiang_at', '');
        $packType = data_get($package, 'pak_type', '');
        $time = $this->time;
        $socketMsg = [
            'package_name' => data_get($player, 'package_name', ''),
            'cp_package_id' => $this->cpPackageId,
            'no' => data_get($player, 'no', ''),
            'name' => data_get($player, 'name', ''),
            'package_id' => data_get($player, 'package_id', ''),
            'sex' => data_get($player, 'sex', ''),
            'when' => $time,
            'age_range' => data_get($player, 'age_range', ''),
            'status' => '正常',
            'quan' => 0,
        ];
        $results = CpPackages::where('cp_packages.package_id', '=', $packageId)
            ->leftjoin('cp_results_final as crf', function ($join) use ($playerId) {
                $join->on('crf.cp_package_id', '=', 'cp_packages.id')
                    ->where('crf.status', '=', 0)
                    ->where('crf.player_id', '=', $playerId);
            })
            ->select('cp_packages.*', 'crf.when', 'crf.time_used', 'crf.speed_allocation', 'crf.id as crf_id', 'crf.is_warn', 'crf.status', 'crf.predist_arrived', 'crf.overtime')
            ->where('cp_packages.is_report', '=', 0)
            ->addSelect(Db::raw("SUBSTRING(DATE_FORMAT(`when`, '%Y-%m-%d %H:%i:%s.%f'),1,23) as `when`"))
            ->orderBy('cp_packages.cp_mileage')
            //            ->groupBy('crf.id')
            ->get()
            ->toArray();
        $statusArr = [];
        $qidianAt = '';
        $lastCpMileage = 0;
        $prefixCpMileage = 0;
        $lastWhen = $qiangAt;
        $prefixWhen = $qiangAt;
        if ($cpMileage > 0.01) {
            foreach ($results as $k => $result) {
                $tmpStatus = data_get($result, 'status', 1);
                if ($tmpStatus !== 0) {
                    continue;
                }
                $tmpCpMileage = data_get($result, 'cp_mileage', 0);

                info('comp', [$tmpCpMileage, $prefixCpMileage]);
                if ($tmpCpMileage >= $cpMileage) {
                    continue;
                } else {
                    $prefixCpMileage = $tmpCpMileage;
                    $prefixWhen = data_get($result, 'when', '');
                }



                // 最后一个打卡距离
//            $prefixCpMileage = $tmpCpMileage;
                // 最后一个打卡时间
//            $prefixWhen = data_get($result, 'when', '');

//            if ($tmpCpMileage >= $cpMileage) {
//                continue;
//            }
//            $crfId = data_get($result, 'crf_id', '');
//            if (empty($crfId)) {
//                continue;
//            }

            }
            if ($cpMileage > 0.01 && $prefixCpMileage > 0.01) {
                $timeUsed = timeDiff2($prefixWhen, $time);
                $mileageDiff = bcsub((string)$cpMileage, (string)$prefixCpMileage, 2);
                if ($mileageDiff == '0') {
                    $peisuMin = 0;
                } else {
                    $peisuMin = round(time2Min($timeUsed) / $mileageDiff, 2);
                }
                if ($peisuMin < $cpPackagePeisu && $cpPackagePeisu > 0) {
                    $statusArr[] = '配速异常';
                    info('z');
                }
            }
        }

        $count = 0;
        if ($packType == 7) {
            $timeQuan = Db::table('time_quan')->where('package_id', '=', $packageId)
                ->first();
            $timeQuanData = data_get($timeQuan, 'data', '');
            $dataArray = json_decode($timeQuanData, true);
            $end = end($dataArray);
            $endCpId = data_get($end, 'cp_id', '');

            foreach ($results as $k => $result) {
                $tmpCpMileage = data_get($result, 'cp_mileage', 0);
                $tmpCpId = data_get($result, 'cp_id', 0);
                if ($tmpCpId == $endCpId && !in_array($tmpCpMileage, [0, 0.01])) {
                    $count ++;
                }

            }
            $count = Db::table('cp_results_final')->where('player_id', '=', $playerId)
                ->where('status', '=', 0)
                ->whereNotIn('mileage', [0, 0.01])
                ->where('cp_id', '=', $endCpId)
                ->count();
        }

        foreach ($results as $k => $result) {
            $tmpStatus = data_get($result, 'status', 1);
            if ($tmpStatus !== 0) {
                continue;
            }
            $tmpCpMileage = data_get($result, 'cp_mileage', 0);
            $lastCpMileage = $tmpCpMileage;

            $lastWhen = data_get($result, 'when', '');
            // 最后一个打卡距离
//            $prefixCpMileage = $tmpCpMileage;
            // 最后一个打卡时间
//            $prefixWhen = $tmpWhen;
//
//            if ($tmpCpMileage >= $cpMileage) {
//                continue;
//            }
//            $crfId = data_get($result, 'crf_id', '');
//            if (empty($crfId)) {
//                continue;
//            }

        }



        info('info', [$lastCpMileage, $prefixCpMileage]);


        foreach ($results as $k => $result) {
            $tmpCpMileage = data_get($result, 'cp_mileage', 0);
            if ($tmpCpMileage > $lastCpMileage) {
                continue;
            }

            if (empty(data_get($result, 'crf_id', ''))) {
                info($tmpCpMileage);
                if (!in_array('缺卡', $statusArr)) {
                    $statusArr[] = '缺卡';
                }
            } else {
//                $tmpStatus = data_get($result, 'status', 1);
//                if ($tmpStatus != 0) {
//                    continue;
//                }
                if (data_get($result, 'is_warn', '0') == 1) {
                    if (!in_array('配速异常', $statusArr)) {
                        $statusArr[] = '配速异常';
                    }
                }

                if ($tmpCpMileage <= 0.01) {
                    $qidianAt = data_get($result, 'when', '');
                }
            }
        }
        $updateP = [];
        $updateP['quan'] = 0;

        if (!in_array('配速异常', $statusArr)) {
            $updateP['peisu_warn'] = 0;
        } else {
            $updateP['peisu_warn'] = 1;
        }
        if (!in_array('缺卡', $statusArr)) {
            $updateP['is_lack'] = 0;
        } else {
            $updateP['is_lack'] = 1;
        }
        info('update', $updateP);



        if ($count > 0) {
            $updateP['quan'] = $count;
            $socketMsg['quan'] = $count;
        }
        if (!empty($updateP)) {
            $tmpp = Db::table('players')->where('id', '=', $playerId)->select('is_lack', 'peisu_warn', 'quan')->first();
            if (data_get($tmpp, 'is_lack', '') != $updateP['is_lack'] ||
                data_get($tmpp, 'peisu_warn', '') != $updateP['peisu_warn'] ||
                data_get($tmpp, 'quan') != $updateP['quan']) {
                Db::table('players')->where('id', '=', $playerId)->update($updateP);
            }
        }
        if (empty($qidianAt)) {
            $qidianAt = $qiangAt;
        }

        $sexConfig = ['1' => '男', '2' => '女'];
        $socketMsg['sex_name'] = data_get($sexConfig, data_get($player, 'sex'), '');
        $socketMsg['result_qiang'] = timeDiff2($qiangAt,$time);
        $socketMsg['result_jing'] = timeDiff2($qidianAt,$time);
        $socketMsg['cp_mileage'] = data_get($this->params, 'cp_mileage', '');
        $socketMsg['cp_name'] = data_get($this->params, 'cp_name', '');
        $socketMsg['cp_id'] = data_get($this->params, 'cp_id', '');
        $socketMsg['status'] = '';
        if (!empty($statusArr)) {
            $socketMsg['status'] = implode(',', $statusArr);
        }

        $activityId = data_get($player, 'activity_id', '');

//        ScreenShow::where('player_id', '=', $playerId)
//            ->where('cp_package_id', '=', $this->cpPackageId)
//            ->orderBy('')

        if ($isNeedNotify) {
            
            // 查询报名信息
            $signup = Db::table('signups')->where('id', $signId)->first();

            // 如果存在报名信息
            if(!empty($signup)){
                $socketMsg['game_id'] = data_get($signup, 'game_id');
                $socketMsg['no'] = data_get($player, 'no');
                $socketMsg['time_used'] = isset($timeUsed) ? $timeUsed : null;
                $socketMsg['game_name'] = data_get($player, 'activity_name');

                // 如果使用了团报
                if(data_get($signup, 'group_id', 0) != 0){
                    $group = Db::table('groups')->select('name')->where('id', data_get($signup, 'group_id'))->first();
                    $socketMsg['group_name'] = data_get($group, 'name');
                }else{
                    $socketMsg['group_name'] = null;
                }

                // 如果加入了团队
                if(data_get($signup, 'team_id', 0) != 0){
                    $team = Db::table('game_teams')->select('team_name')->where('id', data_get($signup, 'team_id'))->first();
                    $socketMsg['team_name'] = data_get($team, 'team_name');
                }else{
                    $socketMsg['group_name'] = null;
                }

                $signup_temp_select = json_decode(data_get($signup, 'temp_selects'), true);
                
                if($signup_temp_select){
                    $socketMsg = array_merge($socketMsg, $signup_temp_select);
                }

                // 遍历报名信息
                foreach($signup as $key => $value){
                    // 如果当前键未被定义，则创建
                    if(!isset($socketMsg[$key])){
                        $socketMsg[$key] = $value;
                    }
                }

                try {
                    // 注入生日标识
                    $this->checkPlayerBirth($signup, $socketMsg);
                } catch (\Exception $e) {
                    info('checkPlayerBirth', [$e->getMessage()]);
                }
            }

            $label = '';
            $show = ScreenShow::create([
                'activity_id' => $activityId,
                'player_id' => $playerId,
                'cp_id' => $cpId,
                'cp_package_id' => $this->cpPackageId,
                'result_jing' => $socketMsg['result_jing'],
                'result_qiang' => $socketMsg['result_qiang'],
                'cp_mileage' => $socketMsg['cp_mileage'],
                'cp_name' => $socketMsg['cp_name'],
                'package_name' => $socketMsg['package_name'],
                'no' => $socketMsg['no'],
                'name' => $socketMsg['name'],
                'package_id' => $socketMsg['package_id'],
                'sex_name' => $socketMsg['sex_name'],
                'when' => $socketMsg['when'],
                'age_range' => $socketMsg['age_range'],
                'quan' => $socketMsg['quan'],
                'status' => $socketMsg['status'],
                'sign_info' => data_get($signup, 'temp_selects', ""),
            ]);

            try {
                // 推送选手大屏
                $this->playerScreenMsg($socketMsg);
            } catch (\Exception $e) {
                info('sendPlayerScreenMsg', [$e->getMessage()]);
            }

            $cacheKey = config('cache.sport_prefix').$activityId.'CROSS_VOICE2APP_LIST_'.$signId;
            $cacheKeyCp = config('cache.sport_prefix').$activityId.'CROSS_VOICE2APP_CP_PACKAGE_'.$signId;

            if (redis()->sadd($cacheKeyCp, $this->cpPackageId)) {
                info('smem', redis()->sMembers($cacheKeyCp));
                redis()->expire($cacheKeyCp, 60 * 60 *24);
                $voiceId = Db::table('app_voice')->insertGetId([
                    'type' => 1,
                    'level' => 101,
                    'is_notify' => 0,
                    'sign_id' => $signId,
                    'content' => "您已到达".$socketMsg['cp_name']."用时".$socketMsg['result_jing'],
                    'time' => Carbon::parse($time)->timestamp,
                    'created_at' => Carbon::now()->toDateTimeString(),
                    'updated_at' => Carbon::now()->toDateTimeString(),
                ]);


                redis()->sadd($cacheKey, $voiceId);
                redis()->expire($cacheKey, 60 * 60 *24);

                $fds = redis()->sMembers(config('cache.prefix')."SCREEN_SOCKET_$activityId");

                $sender = new \Hyperf\WebSocketServer\Sender(ApplicationContext::getContainer());
                if ($fds) {
                    try {

                        foreach ($fds as $fd) {
                            $res = $sender->push((int)$fd, json_encode($socketMsg));
                        }
                    } catch (\Exception $e) {}
                }
                $prefix = 'https://rockysports.cn';
                if (env('APP_ENV') == 'production') {
                    $prefix = 'https://sport.luojiweiye.com';
                }
//                $data = [
//                    'message_id' => data_get($show, 'id', ''),
////                    'level' => 10,
//                    'content' => "您已到达".$socketMsg['package_name']."用时".quzheng($socketMsg['result_jing']),
//                    'time' => Carbon::parse($time)->timestamp,
//                ];
                $data = [
                    'msg' => [
                        'code' => 200,
                    ],
                    'data' => [
                        'tag' => 'voice',
                        'infoData' => [
                            [
                                'message_id' => data_get($show, 'id', ''),
                                'level' => 101,
                                'content' => "您已到达".$socketMsg['cp_name']."用时".time2hz(quzheng($socketMsg['result_jing'])),
                                'time' => Carbon::parse($time)->timestamp,
                            ],
                        ]
                    ]
                ];
                $url = $prefix . '/api/soundplay';
                info('socket 推送明细', [$url, $signId, $data]);
                $postData = ['sign_id' => $signId, 'msg' => json_encode($data)];
//        $postData = ['client_id' => intval($client_id), 'data' => json_encode($return)];

                try {
                    $r = post($url, $postData)->getBody();
                    info('socket 推送 post', [$postData, $r]);
//                    redis()->set(config('cache.prefix')."IS_NOTIFY", '1', 86400);
                } catch (\Exception $e) {
                    info('推送体育播报出错', [$e->getCode(), $e->getMessage(), $e->getLine(), $e->getFile()]);
                }
            }



//            $user_id = Db::table('signups')->where('id', '=', data_get($player, 'sign_id'))->select('user_id')->value('user_id');
//            $clientId = Db::table('user_detail')->where('user_id', '=', $user_id)->value('client_id');
//            $isNotify = redis()->get(config('cache.prefix')."IS_NOTIFY");
//
//            if ($clientId) {
//                $lists[] = [
//                    'client_id' => $clientId,
//                    'data' => json_encode($data),
//                ];
//                $prefix = 'http://position.luojiweiye.com:8001';
//                if (env('APP_ENV') == 'production') {
//                    $prefix = 'http://position.luojiweiye.com:9501';
//                }
//                $url = $prefix . '/system/sportws';
//                info('socket 推送明细', [$url, $data]);
//                $postData = ['lists' => $lists];
////        $postData = ['client_id' => intval($client_id), 'data' => json_encode($return)];
//                info('socket 推送 post', $postData);
//                try {
//                    post($url, $postData);
//                    redis()->set(config('cache.prefix')."IS_NOTIFY", '1', 86400);
//                } catch (\Exception $e) {
//                    info('推送定位出错', [$e->getCode(), $e->getMessage(), $e->getLine(), $e->getFile()]);
//                }
//            }




        }
    }

    public function playerScreenMsg($message)
    {
        $cache_key = config('cache.prefix')."SCREEN_LIST_INDEX_{$message['game_id']}";
        $screen_list_index = redis()->get($cache_key);

        if($screen_list_index === 0 || $screen_list_index === '0'){
            //如果值是0，则说明十分钟前没有数据，则返回
            return;
        }else if(empty($screen_list_index)){
            // 如果缓存为空且不是false状态
            $list = Db::table('screen_list')
            ->select('screen_list.id', 'screen_list.cp_id', 'screen_list.package_id')
            ->where('game_id', '=', $message['game_id'])->where('template_type', '=', 3)
            ->get();

            if(empty($list))
            {
                redis()->set($cache_key, 0, 600);
                return;
            }

            $list = $list->toArray();

            $screen_list_index = [];

            foreach($list as $screen){
                $cp_ids = data_get($screen, 'cp_id')?explode(',', data_get($screen, 'cp_id')):[];
                $package_ids = data_get($screen, 'package_id')?explode(',', data_get($screen, 'package_id')):[];
                foreach($package_ids as $package_id){
                    if(!isset($screen_list_index[$package_id])){
                        $screen_list_index[$package_id] = [];
                    }
                    foreach($cp_ids as $cp_id){
                        if(!isset($screen_list_index[$package_id][$cp_id])){
                            $screen_list_index[$package_id][$cp_id] = [];
                        }
                        $screen_list_index[$package_id][$cp_id][] = data_get($screen, 'id');
                    }
                }
            }

            redis()->set($cache_key, json_encode($screen_list_index), 600);
        }else{
            $screen_list_index = json_decode($screen_list_index, true);
        }

        // 确保 $screen_list_index 是一个数组
        if (!is_array($screen_list_index)) {
            $screen_list_index = [];
        }

        $puch_screen_id = [];
        if(isset($screen_list_index[$message['package_id']]) && isset($screen_list_index[$message['package_id']][$message['cp_id']])){
            $puch_screen_id = $screen_list_index[$message['package_id']][$message['cp_id']];
        }

        // 如果报名有照片，则拼接压缩链接
        if(isset($message['player_photo']) && !empty($message['player_photo'])){
            $player_photos = json_decode($message['player_photo'], true);
            foreach($player_photos as &$player_photo){
                $player_photo = $player_photo.'?imageView2/2/w/750/q/100';
            }
            $message['player_photo'] = json_encode($player_photos);
        }

        $sendPlayerScreenMsgService = new SendPlayerScreenMsgService();

        $now = Carbon::now()->toDateTimeString();

        // 开始推送
        $logs = [];

        info('puch_screen', [$puch_screen_id, $screen_list_index]);
        foreach($puch_screen_id as $screen_id){
            $sendPlayerScreenMsgService->pushPlayerScreenMsg($screen_id, $message);

            $logs[] = [
                'game_id' => $message['game_id'],
                'game_name' => $message['game_name'],
                'package_id' => $message['package_id'],
                'package_name' => $message['package_name'],
                'cp_id' => $message['cp_id'],
                'cp_name' => $message['cp_name'],
                'screen_id' => $screen_id,
                'name' => $message['name'],
                'no' => $message['no'],
                'message' => json_encode($message),
                'created_at' => $now,
                'updated_at' => $now,
            ];
        }

        if($logs){
            Db::table('screen_dashboard_logs')->insert($logs);
        }
    }

    // 检测选手生日 添加生日标识
    public function checkPlayerBirth(&$signup, &$socketMsg){
        // 判断是否有生日字段
        $birth = data_get($signup, 'birth');
        $today = date("m-d");
        $is_birth = 0;

        // 如果没有生日 且证件类型是身份证号
        if(empty($birth) && data_get($signup, 'id_type') == 0){
            $id_num = data_get($signup, 'id_num');
            // 正则表达式匹配身份证号中的生日部分
            $pattern = '/^\d{6}(\d{4})(\d{2})(\d{2})\d{3}[\dX]$/'; // 18位身份证
            $pattern15 = '/^\d{6}(\d{2})(\d{2})(\d{2})\d{3}$/'; // 15位身份证

            $birth = '';

            // 取身份证中的生日
            if (preg_match($pattern, $id_num, $matches)) {
                // 18位身份证：直接提取年月日
                $month = $matches[2];
                $day = $matches[3];
                $birth = "{$month}-{$day}";
            } elseif (preg_match($pattern15, $id_num, $matches)) {
                // 15位身份证：年份需要补全（19xx）
                $month = $matches[2];
                $day = $matches[3];
                $birth = "{$month}-{$day}";
            }
        }else{
            // 把年份即 2000- 这部分字符去掉
            $birth = substr($birth, 5);
        }

        if($birth == $today){
            $is_birth = 1;
        }

        info('is_birth', [$is_birth]);
        //  写入报名备份
        data_set($signup, 'is_birth', $is_birth);

        // 写入报名模板值字段
        $temp_selects = data_get($signup, 'temp_selects');
        $temp_selects = json_decode($temp_selects, true);
        data_set($temp_selects, 'is_birth', $is_birth);
        data_set($signup, 'temp_selects', json_encode($temp_selects));

        // 写入消息
        data_set($socketMsg, 'is_birth', $is_birth);
    }
}
